local type = type
local print = print
local tostring = tostring
local pairs = pairs
local format = string.format

module("utils")

function count(table)
	local c = 0
	for _ in pairs(table) do
		c = c + 1
	end
	return c
end

function dump(name, value, o)
	local dumped = {}
	
	local print = print
	if o then
		print = function (s)
			o:write(s.."\n")
		end
	end
	
	
	local valuetostring = function(key)
		local t = type(key)
		if t == "string" then
			return format("%q", key)
		else
			return tostring(key)
		end
	end
	
	local keytostring = function (dumped, key)
		local tk = type(key)
		if tk == "string" then
			if key:len() > 0 and not key:find("[^%a%d_]") and not key:sub(1, 1):find("%d") then
				return key
			else
				return format("[%q]", key)
			end
		elseif tk == "table" then
			if dumped[key] then
				return "["..dumped[key].."]"
			end
		end
		return "["..valuetostring(key).."]"
	end
	
	local function realdump(name, rname, value, offset)
		local e = offset == "" and "" or ","
		local keyname = keytostring(dumped, name)
		if type(value) == "table" then
			if dumped[value] then
				print(format("%s%s = %s%s", offset, keyname, dumped[value], e))
			else
				dumped[value] = rname
				print(format("%s%s = {", offset, keyname))
				if keyname:sub(1, 1) ~= "[" then
					keyname = "."..keyname
				end
				local roffset = offset.."  "
				local index = 1
				for key, val in pairs(value) do
					local k = keytostring(dumped, key)
					if k:sub(1, 1) ~= "[" then
						k = "."..k
					end
					realdump(key, rname..k, val, roffset)
				end
				print(format("%s}%s", offset, e))
			end
		else
				print(format("%s%s = %s%s", offset, keyname, valuetostring(value), e))
		end
	end
	
	realdump(name, keytostring(nil, name), value, "")
end
